﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Galaxian
{
    public class Engine
    {
        private IRenderer renderer;
        private IUserInterface userInterface;
        private List<GameObject> allObjects;
        public int SleepTime { get; private set; }
        private Ship MyShip;

        public Engine(IRenderer renderer, IUserInterface userInterface, int sleep)
        {
            this.renderer = renderer;
            this.userInterface = userInterface;
            this.SleepTime = sleep;
            this.allObjects = new List<GameObject>();
        }

        public void AddObject(GameObject obj)
        {
            if (obj is EnemyShip)
            {
                this.allObjects.Add((EnemyShip)obj);
            }
            else if (obj is Ship)
            {
                this.AddShip(obj);
            }
            else
            {
                if (obj is Projectile)
                {
                    this.allObjects.Add((Projectile)obj);
                }
            }
        }

        private void AddShip(GameObject ship)
        {
            this.MyShip = ship as Ship;
            this.allObjects.Add(this.MyShip);
        }

        public void MoveShipLeft()
        {
            this.MyShip.MoveLeft();
        }

        public void MoveShipRight()
        {
            this.MyShip.MoveRight();
        }

        public void ShipFire()
        {
            Projectile proj = new Projectile(new Position(this.MyShip.Position.X, this.MyShip.Position.Y), true, false);
            this.MyShip.Shoot(proj);
            this.allObjects.Add(proj);
        }

        public void EnemyFire(List<GameObject> objects)
        {
            List<GameObject> newObj = new List<GameObject>();
            foreach (var obj in objects)
            {
                if (obj.IsShooting && (DateTime.Now - obj.Timer).TotalMilliseconds >= obj.Millsec)
                {
                    Projectile proj = new Projectile(new Position(obj.Position.X, obj.Position.Y), false, true);
                    (obj as EnemyShip).Shoot(proj);
                    newObj.Add(proj);
                    obj.Timer = DateTime.Now;
                }
            }

            objects.AddRange(newObj);
        }

        public virtual void Run()
        {
            bool gameOver = false;
            int count = 1; 
            while (!gameOver && count != 0)
            {
                count = 0;
                this.renderer.RenderAll();
                System.Threading.Thread.Sleep(this.SleepTime);
                this.userInterface.ProcessInput();
                this.EnemyFire(this.allObjects);
                this.renderer.ClearQueue();

                foreach (var obj in this.allObjects)
                {
                    obj.Update();
                    this.renderer.EnqueueForRendering(obj);
                }

                Collision.FindCollisions(this.allObjects);
                if (MyShip.IsDestroyed == true)
                {
                    gameOver = true;
                }
                foreach (var obj in this.allObjects)
                {
                    if (obj is EnemyShip)
                    {
                        count++;
                    }
                    if (obj.IsDestroyed == true && obj is EnemyShip)
                    {
                        MyShip.KillCount++;
                    }
                }

                this.allObjects.RemoveAll(obj => obj.IsDestroyed);
            }
            
            MyShip.PointsForKill = MyShip.KillCount * 10;
            Console.WriteLine("GAME OVER");
            Console.WriteLine("-----KILL COUNT-----");
            Console.WriteLine(MyShip.KillCount);
            Console.WriteLine("-----POINTS-----");
            Console.WriteLine(MyShip.PointsForKill);
        }
    }
}
